package org.jeecg.modules.system.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.*;
import org.jeecg.common.util.encryption.EncryptedString;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysTenant;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.model.SysLoginModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.jeecg.modules.system.util.CodeUtil;
import org.jeecg.modules.system.util.RandImageUtil;
import org.jeecg.modules.veterans.entity.SysLikeRecord;
import org.jeecg.modules.veterans.entity.SysService;
import org.jeecg.modules.veterans.entity.SysVeterans;
import org.jeecg.modules.veterans.service.ISysServiceService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.jeecg.modules.veterans.service.ISysVeteransService;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.util.*;

/**
 * @Author scott
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/sys")
@Api(tags="用户登录")
@Slf4j
public class LoginController {
	@Autowired
	private ISysUserService sysUserService;
	@Autowired
	private SysBaseApiImpl sysBaseApi;
	@Autowired
	private ISysLogService logService;
	@Autowired
    private RedisUtil redisUtil;
	@Autowired
    private ISysDepartService sysDepartService;
	@Autowired
	private ISysTenantService sysTenantService;
	@Autowired
    private ISysDictService sysDictService;
	@Resource
	private BaseCommonService baseCommonService;
	@Autowired
	private ISysVeteransService sysVeteransService;
	@Autowired
	private ISysServiceService sysServiceService;


	@ApiOperation("登录接口")
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel){
		Result<JSONObject> result = new Result<JSONObject>();
		String username = sysLoginModel.getUsername();
		String password = sysLoginModel.getPassword();
//		String smscode = sysLoginModel.getPhoneCode();
		
		//update-begin--Author:scott  Date:20190805 for：暂时注释掉密码加密逻辑，有点问题
		//前端密码加密，后端进行密码解密
		//password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密
		//update-begin--Author:scott  Date:20190805 for：暂时注释掉密码加密逻辑，有点问题

		//update-begin-author:taoyan date:20190828 for:校验验证码
        String captcha = sysLoginModel.getCaptcha();
        if(captcha==null){
            result.error500("验证码无效");
            return result;
        }
        String lowerCaseCaptcha = captcha.toLowerCase();
		String realKey = Md5Util.md5Encode(lowerCaseCaptcha+sysLoginModel.getCheckKey(), "utf-8");
		Object checkCode = redisUtil.get(realKey);
		//当进入登录页时，有一定几率出现验证码错误 #1714
		if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) {
            log.warn("验证码错误，key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode);
			result.error500("验证码错误");
			return result;
		}
		//update-end-author:taoyan date:20190828 for:校验验证码
		
		// 添加手机验证码验证
//		String cacheKey = CodeUtil.getPhoneCodeCacheKey(username);
//		Object code = redisUtil.get(cacheKey);
//		if (oConvertUtils.isEmpty(smscode) || oConvertUtils.isEmpty(code) || !smscode.equals(code)) {
//			result.error500("手机验证码错误");
//			return result;
//		}
		// 考虑验证后是否删除
		//redisUtil.del(cacheKey);
		
		//1. 校验用户是否有效
		//update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
		LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(SysUser::getUsername,username);
		SysUser sysUser = sysUserService.getOne(queryWrapper);
		//update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
		result = sysUserService.checkUserIsEffective(sysUser);
		if(!result.isSuccess()) {
			return result;
		}
		
		//2. 校验用户名或密码是否正确
		//TO DO 二期修改
		String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
//		String userpassword = password;
		String syspassword = sysUser.getPassword();
		//登录验证时，3分钟内连续输错5次密码，锁住帐号;帐号锁住时间为5分钟，5分钟后解封
		String loginId = sysUser.getUsername();//传进来的登录名
		Boolean exit  = redisUtil.hasKey(loginId);//查看缓存是否存在
		//登录进来，第一步判断账户是否锁定，
		if (exit == true && ("lock".equals(redisUtil.get(loginId)))) {
			//redisService.setEx(loginId,"1", 300);//手动解锁
			//获取锁定时间
			long t = redisUtil.unlockTime(loginId)+1;
			result.error500("该帐号登录已锁定,请"+t+"分钟后再试！");
			return result;
		}else
			//第二步判断是否错误次数达到五次，如果达到5次，那就锁定账户，锁定值为lock，锁定时间5分钟
			if (exit == true && "5".equals(redisUtil.get(loginId))) {
				//锁帐号
				redisUtil.set(loginId, "lock");
				//设置锁定5分钟过期时间（秒）
				redisUtil.expire(loginId, 5 * 60);
				//获取锁定时间
				long t = redisUtil.unlockTime(loginId)+1;
				result.error500("该帐号登录已锁定,请"+t+"分钟后再试！");
				return result;
			}else { //其他情况就是错误没有达到五次和账户没有锁定的情况
				//这儿是判断密码如果不一致，那就是登录失败
				if (!syspassword.equals(userpassword)) {
					// 如果缓存存在这个值，那么就加1，记录次数
					if (redisUtil.hasKey(loginId)) {
						String num = (String)redisUtil.get(loginId);
						int i = Integer.parseInt(num); i++;
						redisUtil.set(loginId,String.valueOf(i));
					} else { //如果缓存不存在，起始值是1，有效期3分钟，方法单位为秒
						redisUtil.set(loginId,"1", 180);//五分钟内错误次数
					}
					result.setCode(CommonConstant.SC_PASSWORD_ERROR_530);
					result.setMessage("用户名或密码错误,第 " + redisUtil.get(loginId) + " 次登录失败");
					return result;
				}
			}
		//其余情况就是登录正确的时候，登录成功，记得清除该缓存
		redisUtil.del(loginId);
				
		//用户登录信息
		userInfo(sysUser, result);
		//update-begin--Author:liusq  Date:20210126  for：登录成功，删除redis中的验证码
		redisUtil.del(realKey);
		//update-begin--Author:liusq  Date:20210126  for：登录成功，删除redis中的验证码
		LoginUser loginUser = new LoginUser();
		BeanUtils.copyProperties(sysUser, loginUser);
		baseCommonService.addLog("用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null,loginUser);
        //update-end--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
		return result;
	}


	/**
	 * 【vue3专用】获取用户信息
	 */
	@GetMapping("/user/getUserInfo")
	public Result<JSONObject> getUserInfo(HttpServletRequest request){
		Result<JSONObject> result = new Result<JSONObject>();
		String  username = JwtUtil.getUserNameByToken(request);
		if(oConvertUtils.isNotEmpty(username)) {
			// 根据用户名查询用户信息
			SysUser sysUser = sysUserService.getUserByName(username);
			JSONObject obj=new JSONObject();
			obj.put("userInfo",sysUser);
			obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
			result.setResult(obj);
			result.success("");
		}
		return result;

	}
	
	/**
	 * 退出登录
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/logout")
	public Result<Object> logout(HttpServletRequest request,HttpServletResponse response) {
		//用户退出逻辑
	    String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
	    if(oConvertUtils.isEmpty(token)) {
	    	return Result.error("退出登录失败！");
	    }
	    String username = JwtUtil.getUsername(token);
		LoginUser sysUser = sysBaseApi.getUserByName(username);
	    if(sysUser!=null) {
			//update-begin--Author:wangshuai  Date:20200714  for：登出日志没有记录人员
			baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功！", CommonConstant.LOG_TYPE_1, null,sysUser);
			//update-end--Author:wangshuai  Date:20200714  for：登出日志没有记录人员
	    	log.info(" 用户名:  "+sysUser.getRealname()+",退出成功！ ");
	    	//清空用户登录Token缓存
	    	redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
	    	//清空用户登录Shiro权限缓存
			redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
			//清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
			redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
			//调用shiro的logout
			SecurityUtils.getSubject().logout();
	    	return Result.ok("退出登录成功！");
	    }else {
	    	return Result.error("Token无效!");
	    }
	}
	
	/**
	 * 获取访问量
	 * @return
	 */
	@GetMapping("loginfo")
	public Result<JSONObject> loginfo() {
		Result<JSONObject> result = new Result<JSONObject>();
		JSONObject obj = new JSONObject();
		//update-begin--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
		// 获取一天的开始和结束时间
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		Date dayStart = calendar.getTime();
		calendar.add(Calendar.DATE, 1);
		Date dayEnd = calendar.getTime();
		// 获取系统访问记录
		Long totalVisitCount = logService.findTotalVisitCount();
		obj.put("totalVisitCount", totalVisitCount);
		Long todayVisitCount = logService.findTodayVisitCount(dayStart,dayEnd);
		obj.put("todayVisitCount", todayVisitCount);
		Long todayIp = logService.findTodayIp(dayStart,dayEnd);
		//update-end--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
		obj.put("todayIp", todayIp);
		result.setResult(obj);
		result.success("登录成功");
		return result;
	}
	
	/**
	 * 获取访问量
	 * @return
	 */
	@GetMapping("visitInfo")
	public Result<List<Map<String,Object>>> visitInfo() {
		Result<List<Map<String,Object>>> result = new Result<List<Map<String,Object>>>();
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        Date dayEnd = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date dayStart = calendar.getTime();
        List<Map<String,Object>> list = logService.findVisitCount(dayStart, dayEnd);
		result.setResult(oConvertUtils.toLowerCasePageList(list));
		return result;
	}
	/**
	 * 获取访问量
	 * @return
	 */
	@GetMapping("userData")
	public Result<Map> userData() {
		Result<Map> result = new Result<>();
		Map<String,Object> map = new HashMap<>();
		String boy_total = "0";
		String user_total = "0";
		String veter_total = "0";
		String veterd_total = "0";
		String sysuser_total = "0";

		String siyang_total = "0";
		String suyu_total = "0";
		String shuyang_total = "0";
		String sucheng_total = "0";
		String sihong_total = "0";
		String jingkai_total = "0";
		String ser_total ="0";
		String total_10 = "0";
		String total_20 = "0";
		String total_30 = "0";
		String total_40 = "0";
		String total_50 = "0";
		String total_60 = "0";
		String total_70 = "0";
		String total_80 = "0";



		QueryWrapper<SysService> queryWrapper_sucheng = new QueryWrapper<>();
		List<SysService> list_total = sysServiceService.list(queryWrapper_sucheng);
		queryWrapper_sucheng.eq("area","1");
		List<SysService> list_sucheng = sysServiceService.list(queryWrapper_sucheng);
		QueryWrapper<SysService> queryWrapper_suyu = new QueryWrapper<>();
		queryWrapper_suyu.eq("area","2");
		List<SysService> list_suyu = sysServiceService.list(queryWrapper_suyu);
		QueryWrapper<SysService> queryWrapper_shuyang = new QueryWrapper<>();
		queryWrapper_shuyang.eq("area","3");
		List<SysService> list_shuyang = sysServiceService.list(queryWrapper_shuyang);
		QueryWrapper<SysService> queryWrapper_siyang = new QueryWrapper<>();
		queryWrapper_siyang.eq("area","4");
		List<SysService> list_siyang = sysServiceService.list(queryWrapper_siyang);
		QueryWrapper<SysService> queryWrapper_sihong = new QueryWrapper<>();
		queryWrapper_sihong.eq("area","5");
		List<SysService> list_sihong = sysServiceService.list(queryWrapper_sihong);
		QueryWrapper<SysService> queryWrapper_jingkai = new QueryWrapper<>();
		queryWrapper_jingkai.eq("area","6");
		List<SysService> list_jingkai = sysServiceService.list(queryWrapper_jingkai);
		ser_total = String.valueOf(list_total.size());
		siyang_total = String.valueOf(list_siyang.size());
		suyu_total = String.valueOf(list_suyu.size());
		shuyang_total = String.valueOf(list_shuyang.size());
		sucheng_total = String.valueOf(list_sucheng.size());
		sihong_total = String.valueOf(list_sihong.size());
		jingkai_total = String.valueOf(list_jingkai.size());




		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		List<SysUser> list0 = sysUserService.list(queryWrapper);
		queryWrapper.eq("auth_flag","1");
		List<SysUser> list1 = sysUserService.list(queryWrapper);
		queryWrapper.eq("sex","1");
		List<SysUser> list2 = sysUserService.list(queryWrapper);
		sysuser_total = String.valueOf(list0.size());
		user_total = String.valueOf(list1.size());
		boy_total = String.valueOf(list2.size());
		QueryWrapper<SysVeterans> queryWrapper12 = new QueryWrapper<>();
		List<SysVeterans> list3 = sysVeteransService.list(queryWrapper12);
		queryWrapper12.eq("status","2");
		List<SysVeterans> list4 = sysVeteransService.list(queryWrapper12);


		QueryWrapper<SysVeterans> queryWrapper_age0 = new QueryWrapper<>();
		queryWrapper_age0.lt("age","20");
		List<SysVeterans> list10 = sysVeteransService.list(queryWrapper_age0);
		total_10 =String.valueOf(list10.size());
		QueryWrapper<SysVeterans> queryWrapper_age20 = new QueryWrapper<>();
		queryWrapper_age20.between("age","20","29");
		List<SysVeterans> list20 = sysVeteransService.list(queryWrapper_age20);
		total_20 =String.valueOf(list20.size());
		QueryWrapper<SysVeterans> queryWrapper_age30 = new QueryWrapper<>();
		queryWrapper_age30.between("age","30","39");
		List<SysVeterans> list30 = sysVeteransService.list(queryWrapper_age30);
		total_30 =String.valueOf(list30.size());
		QueryWrapper<SysVeterans> queryWrapper_age40 = new QueryWrapper<>();
		queryWrapper_age40.between("age","40","49");
		List<SysVeterans> list40 = sysVeteransService.list(queryWrapper_age40);
		total_40 =String.valueOf(list40.size());
		QueryWrapper<SysVeterans> queryWrapper_age50 = new QueryWrapper<>();
		queryWrapper_age50.between("age","50","59");
		List<SysVeterans> list50 = sysVeteransService.list(queryWrapper_age50);
		total_50 =String.valueOf(list50.size());
		QueryWrapper<SysVeterans> queryWrapper_age60 = new QueryWrapper<>();
		queryWrapper_age60.between("age","60","69");
		List<SysVeterans> list60 = sysVeteransService.list(queryWrapper_age60);
		total_60 =String.valueOf(list60.size());
		QueryWrapper<SysVeterans> queryWrapper_age70 = new QueryWrapper<>();
		queryWrapper_age70.between("age","70","79");
		List<SysVeterans> list70 = sysVeteransService.list(queryWrapper_age70);
		total_70 =String.valueOf(list70.size());
		QueryWrapper<SysVeterans> queryWrapper_age80 = new QueryWrapper<>();
		queryWrapper_age80.ge("age","80");
		List<SysVeterans> list80 = sysVeteransService.list(queryWrapper_age80);
		total_80 =String.valueOf(list80.size());


		veter_total = String.valueOf(list3.size());
		veterd_total = String.valueOf(list4.size());
		map.put("vtotal",veter_total);
		map.put("vdtotal",veterd_total);
		map.put("utotal",user_total);
		map.put("btotal",boy_total);
		map.put("systotal",sysuser_total);

		map.put("sertotal",ser_total);
		map.put("suchengtotal",sucheng_total);
		map.put("suyutotal",suyu_total);
		map.put("shuyangtotal",shuyang_total);
		map.put("siyangtotal",siyang_total);
		map.put("sihongtotal",sihong_total);
		map.put("jingkaitotal",jingkai_total);
		map.put("total10",total_10);
		map.put("total20",total_20);
		map.put("total30",total_30);
		map.put("total40",total_40);
		map.put("total50",total_50);
		map.put("total60",total_60);
		map.put("total70",total_70);
		map.put("total80",total_80);




		result.setResult(map);
		return result;
	}
	
	/**
	 * 登陆成功选择用户当前部门
	 * @param user
	 * @return
	 */
	@RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)
	public Result<JSONObject> selectDepart(@RequestBody SysUser user) {
		Result<JSONObject> result = new Result<JSONObject>();
		String username = user.getUsername();
		if(oConvertUtils.isEmpty(username)) {
			LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
			username = sysUser.getUsername();
		}
		String orgCode= user.getOrgCode();
		this.sysUserService.updateUserDepart(username, orgCode);
		SysUser sysUser = sysUserService.getUserByName(username);
		JSONObject obj = new JSONObject();
		obj.put("userInfo", sysUser);
		result.setResult(obj);
		return result;
	}

	/**
	 * 短信登录接口
	 * 
	 * @param jsonObject
	 * @return
	 */
	@PostMapping(value = "/sms")
	public Result<String> sms(@RequestBody JSONObject jsonObject) {
		Result<String> result = new Result<String>();
		String username = (String)jsonObject.get("username");
		//String mobile = (String)jsonObject.get("mobile");
		//手机号模式 登录模式: "0"  注册模式: "1"
		String smsmode = (String)jsonObject.get("smsmode");
		//log.info(mobile);
//		if(oConvertUtils.isEmpty(mobile)){
//			result.setMessage("手机号不允许为空！");
//			result.setSuccess(false);
//			return result;
//		}
		if(oConvertUtils.isEmpty(username)){
			result.setMessage("账户不允许为空！");
			result.setSuccess(false);
			return result;
		}
		String cacheKey = CodeUtil.getPhoneCodeCacheKey(username);
		Object object = redisUtil.get(cacheKey);
		if (object != null) {
			result.setMessage("验证码5分钟内，仍然有效！");
			result.setSuccess(false);
			return result;
		}

		//随机数
//		String captcha = RandomUtil.randomNumbers(6);
		String captcha = "376698";
		JSONObject obj = new JSONObject();
    	obj.put("code", captcha);
    	String subPhone = "";
		try {
			boolean b = false;
			//注册模板
			if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {
//				SysUser sysUser = sysUserService.getUserByPhone(mobile);
//				if(sysUser!=null) {
//					result.error500(" 手机号已经注册，请直接登录！");
//					baseCommonService.addLog("手机号已经注册，请直接登录！", CommonConstant.LOG_TYPE_1, null);
//					return result;
//				}
//				b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);
			}else {
				//登录模式，校验用户有效性
				SysUser sysUser = sysUserService.getUserByName(username);
				//SysUser sysUser = sysUserService.getUserByPhone(mobile);
				result = sysUserService.checkUserIsEffective(sysUser);
				if(!result.isSuccess()) {
					String message = result.getMessage();
					if("该用户不存在，请注册".equals(message)){
						result.error500("该用户不存在或未绑定手机号");
					}
					return result;
				}
				
				if(oConvertUtils.isEmpty(sysUser.getPhone())) {
					result.error500("用户不存在或未绑定手机号");
					return result;
				}
				
//				if(!username.equals(sysUser.getUsername())) {
//					result.error500("用户不存在或手机号不匹配");
//					return result;
//				}
				
				/**
				 * smsmode 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板
				 */
				if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
					//登录模板
//					b = DySmsHelper.sendSms(sysUser.getPhone(), obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
					b=true;
					subPhone = sysUser.getPhone().substring(7);
					//log.info(captcha);
				} else if(CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
					//忘记密码模板
//					b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
				}
			}

			if (b == false) {
				result.setMessage("短信验证码发送失败,请稍后重试");
				result.setSuccess(false);
				return result;
			}
			//验证码5分钟内有效
			redisUtil.set(cacheKey, captcha, 300);
			//update-begin--Author:scott  Date:20190812 for：issues#391
			//result.setResult(captcha);
			//update-end--Author:scott  Date:20190812 for：issues#391
			result.setMessage("验证码已发送，尾号：" + subPhone);
			result.setSuccess(true);

//		} catch (ClientException e) {
		} catch (Exception e) {
			e.printStackTrace();
			result.error500(" 短信接口未配置，请联系管理员！");
			return result;
		}
		return result;
	}
	

	/**
	 * 手机号登录接口
	 * 
	 * @param jsonObject
	 * @return
	 */
	//@ApiOperation("手机号登录接口")
	//@PostMapping("/phoneLogin")
	public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
		Result<JSONObject> result = new Result<JSONObject>();
		String phone = jsonObject.getString("mobile");
		
		//校验用户有效性
		SysUser sysUser = sysUserService.getUserByPhone(phone);
		result = sysUserService.checkUserIsEffective(sysUser);
		if(!result.isSuccess()) {
			return result;
		}
		
		String smscode = jsonObject.getString("captcha");
		Object code = redisUtil.get(phone);
		if (!smscode.equals(code)) {
			result.setMessage("手机验证码错误");
			return result;
		}
		//用户信息
		userInfo(sysUser, result);
		//添加日志
		baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功！", CommonConstant.LOG_TYPE_1, null);

		return result;
	}


	/**
	 * 用户信息
	 *
	 * @param sysUser
	 * @param result
	 * @return
	 */
	private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
		String syspassword = sysUser.getPassword();
		String username = sysUser.getUsername();
		// 获取用户部门信息
		JSONObject obj = new JSONObject();
		List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
		obj.put("departs", departs);
		if (departs == null || departs.size() == 0) {
			obj.put("multi_depart", 0);
		} else if (departs.size() == 1) {
			sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
			obj.put("multi_depart", 1);
		} else {
			//查询当前是否有登录部门
			// update-begin--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
			SysUser sysUserById = sysUserService.getById(sysUser.getId());
			if(oConvertUtils.isEmpty(sysUserById.getOrgCode())){
				sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
			}
			// update-end--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
			obj.put("multi_depart", 2);
		}
		// update-begin--Author:sunjianlei Date:20210802 for：获取用户租户信息
		String tenantIds = sysUser.getRelTenantIds();
		if (oConvertUtils.isNotEmpty(tenantIds)) {
			List<Integer> tenantIdList = new ArrayList<>();
			for(String id: tenantIds.split(",")){
				tenantIdList.add(Integer.valueOf(id));
			}
			// 该方法仅查询有效的租户，如果返回0个就说明所有的租户均无效。
			List<SysTenant> tenantList = sysTenantService.queryEffectiveTenant(tenantIdList);
			if (tenantList.size() == 0) {
				result.error500("与该用户关联的租户均已被冻结，无法登录！");
				return result;
			} else {
				obj.put("tenantList", tenantList);
			}
		}
		// update-end--Author:sunjianlei Date:20210802 for：获取用户租户信息
		// 生成token
		String token = JwtUtil.sign(username, syspassword);
		// 设置token缓存有效时间
		redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
		redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
		obj.put("token", token);
		obj.put("userInfo", sysUser);
		obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
		result.setResult(obj);
		result.success("登录成功");
		return result;
	}

	/**
	 * 获取加密字符串
	 * @return
	 */
	@GetMapping(value = "/getEncryptedString")
	public Result<Map<String,String>> getEncryptedString(){
		Result<Map<String,String>> result = new Result<Map<String,String>>();
		Map<String,String> map = new HashMap(5);
		map.put("key", EncryptedString.key);
		map.put("iv",EncryptedString.iv);
		result.setResult(map);
		return result;
	}

	/**
	 * 后台生成图形验证码 ：有效
	 * @param response
	 * @param key
	 */
	@ApiOperation("获取验证码")
	@GetMapping(value = "/randomImage/{key}")
	public Result<String> randomImage(HttpServletResponse response,@PathVariable("key") String key){
		Result<String> res = new Result<String>();
		try {
			//生成验证码
			final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
			String code = RandomUtil.randomString(BASE_CHECK_CODES,4);

			//存到redis中
			String lowerCaseCode = code.toLowerCase();
			String realKey = Md5Util.md5Encode(lowerCaseCode+key, "utf-8");
            log.info("获取验证码，Redis checkCode = {}，key = {}", code, key);
			redisUtil.set(realKey, lowerCaseCode, 60);

			//返回前端
			String base64 = RandImageUtil.generate(code);
			res.setSuccess(true);
			res.setResult(base64);
		} catch (Exception e) {
			res.error500("获取验证码出错"+e.getMessage());
			e.printStackTrace();
		}
		return res;
	}
	
	/**
	 * app登录
	 * @param sysLoginModel
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/mLogin", method = RequestMethod.POST)
	public Result<JSONObject> mLogin(@RequestBody SysLoginModel sysLoginModel) throws Exception {
		Result<JSONObject> result = new Result<JSONObject>();
//		String username = sysLoginModel.getUsername();
//		String password = sysLoginModel.getPassword();
		String username = "visitor";
		String password = "Sqtyjr@223800";
		
		if (oConvertUtils.isEmpty(username) || oConvertUtils.isEmpty(password)) {
			result.error500("请输入用户名和密码");
			return result;
		}
		
//		String smscode = sysLoginModel.getPhoneCode();
//		// 添加手机验证码验证
//		String cacheKey = CodeUtil.getPhoneCodeCacheKey(username);
//		Object code = redisUtil.get(cacheKey);
//		if (oConvertUtils.isEmpty(smscode) || oConvertUtils.isEmpty(code) || !smscode.equals(code)) {
//			result.error500("手机验证码错误");
//			return result;
//		}
		// 考虑验证后是否删除
		//redisUtil.del(cacheKey);
		
		//1. 校验用户是否有效
		SysUser sysUser = sysUserService.getUserByName(username);
		result = sysUserService.checkUserIsEffective(sysUser);
		if(!result.isSuccess()) {
			return result;
		}

		//2. 校验用户名或密码是否正确
		//TO DO
//		String userpassword = password;
		String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
		String syspassword = sysUser.getPassword();
		//登录验证时，3分钟内连续输错5次密码，锁住帐号;帐号锁住时间为5分钟，5分钟后解封
		String loginId = sysUser.getUsername();//传进来的登录名
		Boolean exit  = redisUtil.hasKey(loginId);//查看缓存是否存在
		//登录进来，第一步判断账户是否锁定，
		if (exit == true && ("lock".equals(redisUtil.get(loginId)))) {
			//redisService.setEx(loginId,"1", 300);//手动解锁
			//获取锁定时间
			long t = redisUtil.unlockTime(loginId)+1;
			result.error500("该帐号登录已锁定,请"+t+"分钟后再试！");
			return result;
		}else
			//第二步判断是否错误次数达到五次，如果达到5次，那就锁定账户，锁定值为lock，锁定时间5分钟
			if (exit == true && "5".equals(redisUtil.get(loginId))) {
				//锁帐号
				redisUtil.set(loginId, "lock");
				//设置锁定5分钟过期时间（秒）
				redisUtil.expire(loginId, 5 * 60);
				//获取锁定时间
				long t = redisUtil.unlockTime(loginId)+1;
				result.error500("该帐号登录已锁定,请"+t+"分钟后再试！");
				return result;
			}else { //其他情况就是错误没有达到五次和账户没有锁定的情况
				//这儿是判断密码如果不一致，那就是登录失败
				if (!syspassword.equals(userpassword)) {
					// 如果缓存存在这个值，那么就加1，记录次数
					if (redisUtil.hasKey(loginId)) {
						String num = (String)redisUtil.get(loginId);
						int i = Integer.parseInt(num); i++;
						redisUtil.set(loginId,String.valueOf(i));
					} else { //如果缓存不存在，起始值是1，有效期3分钟，方法单位为秒
						redisUtil.set(loginId,"1", 180);//五分钟内错误次数
					}
					result.setCode(CommonConstant.SC_PASSWORD_ERROR_530);
					result.error500("用户名或密码错误,第 " + redisUtil.get(loginId) + " 次登录失败");
					return result;
				}
			}
		//其余情况就是登录正确的时候，登录成功，记得清除该缓存
		redisUtil.del(loginId);

		/*String orgCode = sysUser.getOrgCode();
		if(oConvertUtils.isEmpty(orgCode)) {
			//如果当前用户无选择部门 查看部门关联信息
			List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
			//update-begin-author:taoyan date:20220117 for: JTC-1068【app】新建用户，没有设置部门及角色，点击登录提示暂未归属部，一直在登录页面 使用手机号登录 可正常
			if (departs == null || departs.size() == 0) {
				*//*result.error500("用户暂未归属部门,不可登录!");
				return result;*//*
			}else{
				orgCode = departs.get(0).getOrgCode();
				sysUser.setOrgCode(orgCode);
				this.sysUserService.updateUserDepart(username, orgCode);
			}
			//update-end-author:taoyan date:20220117 for: JTC-1068【app】新建用户，没有设置部门及角色，点击登录提示暂未归属部，一直在登录页面 使用手机号登录 可正常
		} */

		JSONObject obj = new JSONObject();
		//用户登录信息
		obj.put("userInfo", sysUser);
		
		// 生成token
		String token = JwtUtil.sign(username, syspassword);
		// 设置超时时间
		redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
		redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);

		//token 信息
		obj.put("token", token);
		result.setResult(obj);
		result.setSuccess(true);
		result.setCode(200);
		baseCommonService.addLog("用户名: " + username + ",登录成功[移动端]！", CommonConstant.LOG_TYPE_1, null);
		return result;
	}

	/**
	 * 图形验证码
	 * @param sysLoginModel
	 * @return
	 */
	@RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
	public Result<?> checkCaptcha(@RequestBody SysLoginModel sysLoginModel){
		String captcha = sysLoginModel.getCaptcha();
		String checkKey = sysLoginModel.getCheckKey();
		if(captcha==null){
			return Result.error("验证码无效");
		}
		String lowerCaseCaptcha = captcha.toLowerCase();
		String realKey = Md5Util.md5Encode(lowerCaseCaptcha+checkKey, "utf-8");
		Object checkCode = redisUtil.get(realKey);
		if(checkCode==null || !checkCode.equals(lowerCaseCaptcha)) {
			return Result.error("验证码错误");
		}
		return Result.ok();
	}
	/**
	 * 登录二维码
	 */
	@ApiOperation(value = "登录二维码", notes = "登录二维码")
	@GetMapping("/getLoginQrcode")
	public Result<?>  getLoginQrcode() {
		String qrcodeId = CommonConstant.LOGIN_QRCODE_PRE+IdWorker.getIdStr();
		//定义二维码参数
		Map params = new HashMap(5);
		params.put("qrcodeId", qrcodeId);
		//存放二维码唯一标识30秒有效
		redisUtil.set(CommonConstant.LOGIN_QRCODE + qrcodeId, qrcodeId, 30);
		return Result.OK(params);
	}
	/**
	 * 扫码二维码
	 */
	@ApiOperation(value = "扫码登录二维码", notes = "扫码登录二维码")
	@PostMapping("/scanLoginQrcode")
	public Result<?> scanLoginQrcode(@RequestParam String qrcodeId, @RequestParam String token) {
		Object check = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId);
		if (oConvertUtils.isNotEmpty(check)) {
			//存放token给前台读取
			redisUtil.set(CommonConstant.LOGIN_QRCODE_TOKEN+qrcodeId, token, 60);
		} else {
			return Result.error("二维码已过期,请刷新后重试");
		}
		return Result.OK("扫码成功");
	}


	/**
	 * 获取用户扫码后保存的token
	 */
	@ApiOperation(value = "获取用户扫码后保存的token", notes = "获取用户扫码后保存的token")
	@GetMapping("/getQrcodeToken")
	public Result getQrcodeToken(@RequestParam String qrcodeId) {
		Object token = redisUtil.get(CommonConstant.LOGIN_QRCODE_TOKEN + qrcodeId);
		Map result = new HashMap(5);
		Object qrcodeIdExpire = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId);
		if (oConvertUtils.isEmpty(qrcodeIdExpire)) {
			//二维码过期通知前台刷新
			result.put("token", "-2");
			return Result.OK(result);
		}
		if (oConvertUtils.isNotEmpty(token)) {
			result.put("success", true);
			result.put("token", token);
		} else {
			result.put("token", "-1");
		}
		return Result.OK(result);
	}

}